package controller;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Vector;
import java.util.Calendar;
import java.util.Date;
import model.*;
import view.AppointmentView;

/**
 * 07-01-2010
 * 
 * This class is the controller for saving all information from AppointmentView.
 * 
 * @author Stijn Kliemesch
 */
public class AppointmentController {

	private static AppointmentView view;
	private static AppointmentModel model;

	/**
	 * Needs the model to initialize.
	 * Initiates the AppointmentView singleton and adds is as an observer
	 * to the given model.
	 * 
	 * @param newModel
	 */
	public AppointmentController(AppointmentModel newModel) {
		if(newModel == null) {
			throw new NullPointerException();
		}
		model = newModel;
		view = AppointmentView.getAppointmentView(this);
		model.addObserver(view);
	}

	/**
	 * This opens up the appointment frame and sets it to the state of 
	 * making a new appointment.
	 */
	public void newAppointment() {
		view.setAppointmentId(0);
		view.setInputTitle("");
		view.setInputStartDateTime(2010, 01, 01, 01, 00);
		view.setInputEndDateTime(2010, 01, 01, 01, 00);
		view.setInputLocation("");
		view.setInputContactPerson("");
		view.setInputDescription("");
		view.setInputCategory(null);
		view.setInputIsWholeDays(false);
		view.resetErrors();
		view.showNewOrEditAppointmentOnBool(true);
	}

	/**
	 * This opens up the appointment frame and sets it to the state of 
	 * editing an existing appointment.
	 * 
	 * @param id The id of the appointment in the database
	 */
	public void editAppointment(int id) {
		AppointmentDataModel appointment = model.getAppointment(id);
		if(appointment != null) {
			view.setAppointmentId(id);
			view.setInputTitle(appointment.getTitle());
			view.setInputStartDateTime(appointment.getStartDate().get(Calendar.YEAR),
					appointment.getStartDate().get(Calendar.MONTH),
					appointment.getStartDate().get(Calendar.DAY_OF_MONTH)+1,
					appointment.getStartDate().get(Calendar.HOUR_OF_DAY),
					appointment.getStartDate().get(Calendar.MINUTE));
			view.setInputEndDateTime(appointment.getEndDate().get(Calendar.YEAR),
					appointment.getEndDate().get(Calendar.MONTH),
					appointment.getEndDate().get(Calendar.DAY_OF_MONTH)+1,
					appointment.getEndDate().get(Calendar.HOUR_OF_DAY),
					appointment.getEndDate().get(Calendar.MINUTE));
			view.setInputLocation(appointment.getLocation());
			view.setInputContactPerson(appointment.getContact());
			view.setInputCategory(appointment.getCategory());
			view.setInputDescription(appointment.getDescription());
			if(isAppointmentScheduledForWholeDays(appointment)) {
				view.setInputIsWholeDays(true);
			} else {
				view.setInputIsWholeDays(false);
			}
			view.resetErrors();
			view.showNewOrEditAppointmentOnBool(false);
		}
	}

	/**
	 * This method deletes the appointment from the database.
	 * 
	 * @param id The id of the appointment in the database
	 */
	public void deleteAppointment(int id) {
		model.deleteAppointment(id);
	}

	/**
	 * This method adds a new appointment to the database through the model.
	 * 
	 * @param appointment
	 */
	public void addAppointment(AppointmentDataModel appointment) {
		model.addAppointment(appointment);
	}
	
	/**
	 * This method edits an existing apointment in the database through the model
	 * 
	 * @param appointment
	 */
	public void updateAppointment(AppointmentDataModel appointment) {
		model.editAppointment(appointment);
	}

	/**
	 * This method checks the input and turns it into a formatted string.
	 * 
	 * @param year 4 digits
	 * @param month 2 or 1 digit(s)
	 * @param day 2 or 1 digit(s)
	 * @param hour 2 or 1 digit(s)
	 * @param minute 2 or 1 digit(s)
	 * @return "YYYY-MM-DD HH:MM"
	 */
	public String convertDataToDateTime(String year, String month, String day,
			String hour, String minute) {

		//controles op de invoer
		if(month.length() == 1) {
			month = "0" + month;
		}
		if(day.length() == 1) {
			day = "0" + day;
		}
		if(hour.length() == 1) {
			hour = "0" + hour;
		}
		if(minute.length() == 1) {
			minute = "0" + minute;
		}

		String date = year+"-"+month+"-"+day+" "+hour+":"+minute;

		return date;
	}
	
	/**
	 * Gets the list of categories.
	 * 
	 * @return An instance of Vector with the CategoryDataModel type
	 */
	public Vector<CategoryDataModel> getCategoryList() {
		Vector<CategoryDataModel> list = new Vector<CategoryDataModel>();
		list = model.getAllCategories();	
		return list;
	}

	/**
	 * This method checks if the inputed date is a correct one.
	 * Goes by the format yyyy-MM-dd HH:mm
	 * 
	 * @param date the input Date
	 * @return True on valid date, false on invalid or unparse-able date string.
	 */
	public boolean isValidDate(String date) {
		
		String[] splitDateString = date.split(" ");
		String[] splitDate = splitDateString[0].split("-");
		String[] splitTime = splitDateString[1].split(":");

		if (splitDate[0].length() != 4 || splitDate[1].length() != 2 || splitDate[2].length() != 2 || splitTime[0].length() != 2 || splitTime[1].length() != 2){
			return false;		
		}
		else{
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");
			Date validatedDate;
			
			try {
				validatedDate = sdf.parse(date);
			} catch (ParseException e) {
				return false;
			}
			
			if (!sdf.format(validatedDate).equals(date)) {
				return false;
			} else {
				return true;
			}						
		}
	}
				
	
	/**
	 * This method checks if the startdate is before the enddate.
	 * Goes by the format yyyy-MM-dd HH:mm
	 * input 2 strings in the format of yyyy-MM-dd HH:mm (EXAMPLE: "1994-02-12 15:11", "1994-03-12 15:11")
	 * @return True if startdate is before the enddate, false if otherwise.
	 */
	public boolean startIsBeforeEnd(String start, String end) {

		String[] splitStartDateString = start.split(" ");
		String[] splitStartDate = splitStartDateString[0].split("-");
		String[] splitStartTime = splitStartDateString[1].split(":");

		String[] splitEndDateString = end.split(" ");
		String[] splitEndDate = splitEndDateString[0].split("-");
		String[] splitEndTime = splitEndDateString[1].split(":");


		//TODO MOET MOOIERE VERSIE VOOR KOMEN, zonder if lijst
		//deze code hier controleert of start voor end ligt of niet
		//De einddatum-tijd moet voor de startdatum-tijd komen, niet erna en niet gelijk
		//year check
		if(Integer.valueOf(splitEndDate[0]) > Integer.valueOf(splitStartDate[0])) {
			return true;
		} else if(Integer.valueOf(splitEndDate[0]).equals(Integer.valueOf(splitStartDate[0]))) {
			//month check
			if(Integer.valueOf(splitEndDate[1]) > Integer.valueOf(splitStartDate[1])) {
				return true;
			} else if(Integer.valueOf(splitEndDate[1]).equals(Integer.valueOf(splitStartDate[1]))) {
				//day check
				if(Integer.valueOf(splitEndDate[2]) > Integer.valueOf(splitStartDate[2])) {
					return true;
				} else if(Integer.valueOf(splitEndDate[2]).equals(Integer.valueOf(splitStartDate[2]))) {
					//Whole day check
					if(view.getInputIsWholeDays()) {
						return true;
					} else {
						//hour check
						if(Integer.valueOf(splitEndTime[0]) > Integer.valueOf(splitStartTime[0])) {
							return true;
						} else if(Integer.valueOf(splitEndTime[0]).equals(Integer.valueOf(splitEndTime[0]))) {
							//minute check
							if(Integer.valueOf(splitEndTime[1]) > Integer.valueOf(splitStartTime[1])) {
								return true;
							} else {
								return false;
							}
						} else {
							return false;
						}
					}
				} else {
					return false;
				}
			} else {
				return false;
			}
		} else {
			return false;
		}
	}
	
	/**
	 * Checks if an appointment is scheduled to use whole days or not
	 * @param appointment
	 */
	public boolean isAppointmentScheduledForWholeDays(AppointmentDataModel appointment) {
		if(appointment.getStartDate().get(Calendar.HOUR_OF_DAY) == 0 &&
				appointment.getStartDate().get(Calendar.MINUTE) == 0 &&
				appointment.getEndDate().get(Calendar.HOUR_OF_DAY) == 23 &&
				appointment.getEndDate().get(Calendar.MINUTE) == 59) {
			return true;
		} else {
			return false;
		}
	}
	
	/**
	 * Sets the titleTextField's contents
	 * @param inputText Change the title textfield contents
	 */
	public void setInputTitle(String inputText) {
		view.setInputTitle(inputText);
	}

	/**
	 * Sets the start time and date in the textfields.
	 */
	public void setInputStartDateTime(int year, int month, int day, int hour, int minute) {
		view.setInputStartDateTime(year, month, day, hour, minute);
	}

	/**
	 *  Sets the end time and date in the textfields.
	 */
	public void setInputEndDateTime(int year, int month, int day, int hour, int minute) {
		view.setInputEndDateTime(year, month, day, hour, minute);
	}

	/**
	 * Sets the locationTextField's contents.
	 * 
	 * @param inputText Change the location textfield contents
	 */
	public void setInputLocation(String inputText) {
		view.setInputLocation(inputText);
	}

	/**
	 * 
	 * Sets the contactpersonTextField's contents.
	 * 
	 * @param inputText Change the contactperson textfield contents
	 */
	public void setInputContactPerson(String inputText) {
		view.setInputContactPerson(inputText);
	}

	/**
	 * Sets the descriptionTextArea's contents.
	 * 
	 * @param inputText Change the description textarea contents
	 */
	public void setInputDescription(String inputText) {
		view.setInputDescription(inputText);
	}

	/**
	 * Sets the categoryField's contents.
	 * 
	 * @param inputCategory Select the category
	 */
	public void setInputCategory(CategoryDataModel inputCategory) {
		view.setInputCategory(inputCategory);
	}

	/**
	 * Sets the appointment id for appointment editing purposes.
	 */
	public void setAppointmentId(int id) {
		view.setAppointmentId(id);
	}

	/**
	 * Gets all the categories.
	 * 
	 * @return the entire list of categories from the model.
	 */
	public Vector<CategoryDataModel> getAllCategories() {
		return model.getAllCategories();
	}
	
	/**
	 * Returns a list of appointments based on the search key
	 * 
	 * @param query The search string.
	 * @return An instance of Vector with the AppointmentDataModel type
	 */
	public Vector<AppointmentDataModel> searchAppointments(String query) {
		return model.searchAppointments(query);
	}

}
